<?php
// +----------------------------------------------------------------------
// | Author: derek <693472824@qq.com> <http://www.bloveambition.com/>
// +----------------------------------------------------------------------

namespace Blovex4\Logic;
use Think\Model;
use Think\Upload;

/**
 * 文件模型
 * 负责文件的下载和上传
 * @author derek <lixm@my818.com>
 */

class AttachmentLogic extends BaseLogic{

    /**
     * 文件上传
     * @param  array  $files   要上传的文件列表（通常是$_FILES数组）
     * @param  array  $setting 文件上传配置
     * @param  string $driver  上传驱动名称
     * @param  array  $config  上传驱动配置
     * @return array           文件上传成功后的信息
     * @author derek <lixm@my818.com>
     */
    public function upload($files, $config, $driver = 'Local', $driverConfig = null, $status='1'){
        
        // 上传文件 
        $config['callback'] = array($this, 'isFile');
		$config['removeTrash'] = array($this, 'removeTrash');
		
        $Upload = new Upload($config, $driver, $driverConfig);
        $info   = $Upload->upload($files);

        $attModel = D('Attachment');
        
        // 设置文件保存位置 
		$attModel->_auto[] = array('location', 'local' === strtolower($driver) ? 0 : 1, self::MODEL_INSERT);

        if($info){ //文件上传成功，记录文件信息
            
            foreach ($info as $key => &$value) {
                
                // 已经存在文件记录
                if(isset($value['att_id']) && is_numeric($value['att_id'])){
                    continue;
                }
                
                $value['status'] = $status;
                $value['fullpath'] = $config['rootPath'].$value['savepath'].$value['savename']; //在模板里的url路径

                // 记录文件信息 
                if($attModel->create($value) && ($att_id = $attModel->add())){
                    $value['att_id'] = $att_id;
                } else {
                    //TODO: 文件上传成功，但是记录文件信息失败，需记录日志
                    unset($info[$key]);
                }
            }
            return $info; //文件上传成功
            
        } else {
            $this->error = $Upload->getError();
            return false;
        }
    }
    
    /**
     * 配置项图集、合同相关图等上传
     * @param  array  $files   要上传的文件列表（通常是$_FILES数组）
     * @param  array  $setting 文件上传配置
     * @param  string $driver  上传驱动名称
     * @param  array  $config  上传驱动配置
     * @return array           文件上传成功后的信息
     * @author derek <lixm@my818.com>
     */
    public function uploadOther($files, $config, $driver = 'Local', $driverConfig = null, $model=null, $data=array()){
    
        $model = empty($model) ? D('Attachment') : $model;
    
        $Upload = new Upload($config, $driver, $driverConfig);
        $info   = $Upload->upload($files);
    
        if($info){ //文件上传成功，记录文件信息
    
            foreach ($info as $key => &$value) {
    
                $value['fullpath'] = $config['rootPath'].$value['savepath'].$value['savename']; //在模板里的url路径
    
                $resultArray = array_merge($value, $data);
    
                // 记录文件信息
                if($model->create($resultArray) && ($gallery_id = $model->add())){
                    $value['att_id'] = $gallery_id;
                } else {
                    unset($info[$key]);
                }
            }
            return $info; //文件上传成功
    
        } else {
            $this->error = $Upload->getError();
            return false;
        }
    }
    

    /**
     * 上传文件回调函数
     * 检测当前上传的文件是否已经存在
     * @param  array   $file 文件上传数组
     * @return boolean       文件信息， false - 不存在该文件
     * @author derek <lixm@my818.com>
     */
    public function isFile($file){
        
        if(empty($file['md5'])){
            throw new \Exception('缺少参数:md5');
        }
        
        $attModel = D('Attachment');
        // 查找文件 
        $map = array('md5' => $file['md5'],'sha1'=>$file['sha1'],);
        return $attModel->field(true)->where($map)->find();
    }

	/**
	 * 清除数据库存在但本地不存在的数据
	 * @param $data
	 * @author derek <lixm@my818.com>
	 */
	public function removeTrash($data){
	    $attModel = D('Attachment');
		$attModel->where(array('att_id'=>$data['id'],))->delete();
	}
	
	/**
	 * 下载文件
	 * @param  number $id 文档ID
	 * @return boolean    下载失败返回false
	 */
	public function download($attID){
	    
	    $attModel = $this->find($attID);
	    
	    if(empty($attModel)){
	        $this->error = "文件不存在";
	        return false;
	    }
	    
	    /* 下载文件 */
	    switch ($attModel['location']) {
	        
	        case 0: //下载本地文件
	            $attModel['rootpath'] = C('UPLOAD_PICTURE_CONFIG.rootPath');
	            return $this->downLocalFile($attModel);
                	            
	        case 1: //TODO: 下载远程FTP文件
	            break;
	        
	        default:
	            $this->error = '不支持的文件存储类型！';
	            return false;
	    
	    }
	}
	
	/**
	 * 下载本地文件
	 * @param  array    $file     文件信息数组
	 * @param  callable $callback 下载回调函数，一般用于增加下载次数
	 * @param  string   $args     回调函数参数
	 * @return boolean            下载失败返回false
	 */
	private function downLocalFile($file){
	    
	    if(is_file($file['rootpath'].$file['savepath'].$file['savename']) || is_file($file['fullpath'])){
	
	        /* 执行下载 */ //TODO: 大文件断点续传
	        header("Content-Description: File Transfer");
	        header('Content-type: ' . $file['mime']);
	        header('Content-Length:' . $file['size']);
	        
	        if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) { //for IE
	            
	            header('Content-Disposition: attachment; filename="' . rawurlencode($file['name']) . '"');
	        } else {
	            
	            header('Content-Disposition: attachment; filename="' . $file['name'] . '"');
	        }
	        
	        $path = is_file($file['fullpath']) ? $file['fullpath'] : $file['rootpath'].$file['savepath'].$file['savename'];
	        
	        readfile($path);
	        exit;
	        
	    } else {
	        
	        $this->error = '文件已被删除！';
	        return false;
	    }
	}

}
